#ifndef PCPS_PTHREAD_BARRIER_HEADER
#define PCPS_PTHREAD_BARRIER_HEADER

#include <src/pcps.h>

namespace pcps {

  struct pthread_barrier_t {

      pthread_mutex_t _mutex;
      pthread_cond_t _cond;
      int _count;
      int _nthread;

      pthread_barrier_t() : _count(0), _nthread(0) {}

      void init(int n) {
        _count = 0;
        _nthread = n;
        pthread_mutex_init(&_mutex, NULL);
        pthread_cond_init(&_cond, NULL);
      }

      void destroy() {
        pthread_cond_destroy(&_cond);
        pthread_mutex_destroy(&_mutex);
      }

      void wait() {
        pthread_mutex_lock(&_mutex);
        _count += 1;
        if (_count > _nthread) {
          throw pcps::Exception( (boost::format("Error in pcps::pthread_barrier_t::wait().  count > nthread")).str() );
        } else if (_count == _nthread) {
          _count = 0;
          pthread_cond_broadcast(&_cond);
        } else {
          pthread_cond_wait(&_cond, &_mutex);
        }
        pthread_mutex_unlock(&_mutex);
      }

  };

  inline void pthread_barrier_init(pcps::pthread_barrier_t * b, void * x, int n) {
    b->init(n);
  }

  inline void pthread_barrier_destroy(pcps::pthread_barrier_t * b) {
    b->destroy();
  }

  inline void pthread_barrier_wait(pcps::pthread_barrier_t * b) {
    b->wait();
  }

} // end namespace pcps

#endif
